package com.zlp.mall.upms.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zlp.mall.core.constant.enums.StatusEnum;
import com.zlp.mall.core.utils.BeanToUtils;
import com.zlp.mall.core.utils.api.Pager;
import com.zlp.mall.redis.service.RedisService;
import com.zlp.mall.redis.utils.RupmsConstants;
import com.zlp.mall.upms.dto.req.UserCreateReq;
import com.zlp.mall.upms.dto.resp.UserQueryReq;
import com.zlp.mall.upms.dto.resp.UserResp;
import com.zlp.mall.upms.entity.User;
import com.zlp.mall.upms.mapper.UserMapper;
import com.zlp.mall.upms.service.UserRoleService;
import com.zlp.mall.upms.service.UserService;
import com.zlp.mall.upms.dto.CacheInfo;
import com.zlp.mall.upms.dto.req.LoginUserReq;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author Zou.LiPing
 * @since 2021-04-03
 */
@Service
@RequiredArgsConstructor
@Slf4j(topic = "UserServiceImpl")
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();
    private final UserRoleService userRoleService;
    private final RedisService redisService;

    @Override
    public CacheInfo login(LoginUserReq loginReq) {

        log.info("login.req loginReq={}", JSON.toJSONString(loginReq));
        CacheInfo cacheInfo = new CacheInfo();
        return cacheInfo;
    }

    @Override
    public Pager<UserResp> getUserPage(UserQueryReq userQueryReq) {

        log.info("getUserPage.req userQueryReq={}", JSON.toJSONString(userQueryReq));
        Page page = new Page<>(userQueryReq.getPageNumber(),userQueryReq.getPageSize());
        QueryWrapper<User> queryWapper = new QueryWrapper<>(new User());
        queryWapper.eq("del_flag",userQueryReq.getStatus());
        IPage<User> pager = baseMapper.selectPage(page, queryWapper);
        if (Objects.nonNull(pager) && CollectionUtil.isNotEmpty(pager.getRecords())) {
            List<User> records = pager.getRecords();
            List<UserResp> userRespList = BeanToUtils.entityToList(records, UserResp.class);
            return new Pager<>(userQueryReq.getPageNumber(),userQueryReq.getPageSize(),(int)pager.getPages(),pager.getTotal(),userRespList);
        }
        return new Pager<>();
    }

    @Override
    public UserResp getUserInfo(Long userId) {

        log.info("getUserInfo.req userId={}", userId);
        User user = baseMapper.selectById(userId);
        String key = RupmsConstants.USER+RupmsConstants.DETAIL+ StrUtil.COLON+userId;
        Object value = redisService.get(key);
        if (Objects.nonNull(value)) {
            return (UserResp) value;
        }
        UserResp userResp = BeanToUtils.dtoToDo(user, UserResp.class);
        redisService.setHours(key,userResp,1);
        return userResp;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addUser(UserCreateReq userCreateReq) {

        log.info("addUser.req userCreateReq={}", JSON.toJSONString(userCreateReq));
        User sysUser = BeanToUtils.dtoToDo(userCreateReq,User.class);
        sysUser.setDelFlag(StatusEnum.NORMAL.getValue());
        sysUser.setPassword(ENCODER.encode(userCreateReq.getPassword()));
        baseMapper.insert(sysUser);
        if (CollectionUtil.isNotEmpty(userCreateReq.getRole())) {
            userRoleService.saveBatchRole(sysUser.getUserId(),userCreateReq.getRole());
        }
        return Boolean.TRUE;
    }

}
